return 0;
}
-int pirq_guest_bindable(int irq, int will_share)
-{
- irq_desc_t *desc = &irq_desc[irq];
- irq_guest_action_t *action;
- unsigned long flags;
- int okay;
-
- spin_lock_irqsave(&desc->lock, flags);
-
- action = (irq_guest_action_t *)desc->action;
-
- /*
- * To be bindable the IRQ must either be not currently bound (1), or
- * it must be shareable (2) and not at its share limit (3).
- */
- okay = ((!(desc->status & IRQ_GUEST) && (action == NULL)) || /* 1 */
- (action->shareable && will_share && /* 2 */
- (action->nr_guests != IRQ_MAX_GUESTS))); /* 3 */
-
- spin_unlock_irqrestore(&desc->lock, flags);
- return okay;
-}
#endif
#ifdef XEN
BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
BI(x,c) BI(x,d) BI(x,e) BI(x,f)
-/*
- * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x20-0x2f)
- */
-BUILD_16_IRQS(0x0)
-
-#ifdef CONFIG_X86_IO_APIC
-/*
- * The IO-APIC gives us many more interrupt sources. Most of these
- * are unused but an SMP system is supposed to have enough memory ...
- * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
- * across the spectrum, so we really want to be prepared to get all
- * of these. Plus, more powerful systems might have more than 64
- * IO-APIC registers.
- *
- * (these are usually mapped into the 0x20-0xff vector range)
- */
-BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
+BUILD_16_IRQS(0x0) BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
-BUILD_16_IRQS(0xc)
-#endif
+BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) BUILD_16_IRQS(0xe) BUILD_16_IRQS(0xf)
#undef BUILD_16_IRQS
#undef BI
IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
- void (*interrupt[NR_IRQS])(void) = {
- IRQLIST_16(0x0),
-
-#ifdef CONFIG_X86_IO_APIC
- IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
+ static void (*interrupt[])(void) = {
+ IRQLIST_16(0x0), IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
- IRQLIST_16(0xc)
-#endif
+ IRQLIST_16(0xc), IRQLIST_16(0xd), IRQLIST_16(0xe), IRQLIST_16(0xf)
};
#undef IRQ
static void end_8259A_irq (unsigned int irq)
{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ if (!(irq_desc[irq_to_vector(irq)].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
enable_8259A_irq(irq);
}
{
disable_irq_nosync(irq);
io_apic_irqs &= ~(1<<irq);
- irq_desc[irq].handler = &i8259A_irq_type;
+ irq_desc[irq_to_vector(irq)].handler = &i8259A_irq_type;
enable_irq(irq);
}
for ( i = 0; i < NR_IRQS; i++ )
{
irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].handler = (i<16) ? &i8259A_irq_type : &no_irq_type;
+ irq_desc[i].handler = &no_irq_type;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
spin_lock_init(&irq_desc[i].lock);
- set_intr_gate(FIRST_EXTERNAL_VECTOR+i, interrupt[i]);
+ set_intr_gate(i, interrupt[i]);
+ }
+
+ for ( i = 0; i < 16; i++ )
+ {
+ vector_irq[LEGACY_VECTOR(i)] = i;
+ irq_desc[LEGACY_VECTOR(i)].handler = &i8259A_irq_type;
}
/*
*/
irq_vector[0] = FIRST_DEVICE_VECTOR;
vector_irq[FIRST_DEVICE_VECTOR] = 0;
- set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
/* Various IPI functions. */
set_intr_gate(EVENT_CHECK_VECTOR, event_check_interrupt);
} irq_2_pin[PIN_MAP_SIZE];
int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
+#if 0
#ifdef CONFIG_PCI_MSI
#define vector_to_irq(vector) \
(platform_legacy_irq(vector) ? vector : vector_irq[vector])
#else
#define vector_to_irq(vector) (vector)
#endif
+#endif
/*
* The common case is 1:1 IRQ<->pin mappings. Sometimes there are
static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
{
- if (use_pci_vector() && !platform_legacy_irq(irq)) {
- if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
- trigger == IOAPIC_LEVEL)
- irq_desc[vector].handler = &ioapic_level_type;
- else
- irq_desc[vector].handler = &ioapic_edge_type;
- set_intr_gate(vector, interrupt[vector]);
- } else {
- if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
- trigger == IOAPIC_LEVEL)
- irq_desc[irq].handler = &ioapic_level_type;
- else
- irq_desc[irq].handler = &ioapic_edge_type;
- set_intr_gate(vector, interrupt[irq]);
- }
+ if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ trigger == IOAPIC_LEVEL)
+ irq_desc[vector].handler = &ioapic_level_type;
+ else
+ irq_desc[vector].handler = &ioapic_edge_type;
}
void __init setup_IO_APIC_irqs(void)
* The timer IRQ doesn't have to know that behind the
* scene we have a 8259A-master in AEOI mode ...
*/
- irq_desc[0].handler = &ioapic_edge_type;
+ irq_desc[IO_APIC_VECTOR(0)].handler = &ioapic_edge_type;
/*
* Add it to the IO-APIC irq-routing table:
*/
static void ack_edge_ioapic_irq(unsigned int irq)
{
- if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
+ if ((irq_desc[IO_APIC_VECTOR(irq)].status & (IRQ_PENDING | IRQ_DISABLED))
== (IRQ_PENDING | IRQ_DISABLED))
mask_IO_APIC_irq(irq);
ack_APIC_irq();
*/
for (irq = 0; irq < NR_IRQS ; irq++) {
int tmp = irq;
+#if 0
if (use_pci_vector()) {
if (!platform_legacy_irq(tmp))
if ((tmp = vector_to_irq(tmp)) == -1)
continue;
}
+#endif
if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
/*
* Hmm.. We don't have an entry for this,
*/
if (irq < 16)
make_8259A_irq(irq);
- else
- /* Strange. Oh, well.. */
- irq_desc[irq].handler = &no_irq_type;
}
}
}
*/
disable_8259A_irq(0);
vector = assign_irq_vector(0);
- set_intr_gate(vector, interrupt[0]);
+
+ irq_desc[IO_APIC_VECTOR(0)].action = irq_desc[LEGACY_VECTOR(0)].action;
+ irq_desc[IO_APIC_VECTOR(0)].depth = 0;
+ irq_desc[IO_APIC_VECTOR(0)].status &= ~IRQ_DISABLED;
/*
* Subtle, code in do_timer_interrupt() expects an AEOI
printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
disable_8259A_irq(0);
- irq_desc[0].handler = &lapic_irq_type;
+ irq_desc[vector].handler = &lapic_irq_type;
apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */
enable_8259A_irq(0);
return 0;
/* Set the correct irq-handling type. */
- irq_desc[irq].handler = rte.trigger ?
+ irq_desc[IO_APIC_VECTOR(irq)].handler = rte.trigger ?
&ioapic_level_type: &ioapic_edge_type;
/* Record the pin<->irq mapping. */
irq_desc_t irq_desc[NR_IRQS];
-static void __do_IRQ_guest(int irq);
+static void __do_IRQ_guest(int vector);
void no_action(int cpl, void *dev_id, struct cpu_user_regs *regs) { }
inline void disable_irq_nosync(unsigned int irq)
{
- irq_desc_t *desc = &irq_desc[irq];
+ unsigned int vector = irq_to_vector(irq);
+ irq_desc_t *desc = &irq_desc[vector];
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
spin_unlock_irqrestore(&desc->lock, flags);
}
-void disable_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- do { smp_mb(); } while ( irq_desc[irq].status & IRQ_INPROGRESS );
-}
-
void enable_irq(unsigned int irq)
{
- irq_desc_t *desc = &irq_desc[irq];
+ unsigned int vector = irq_to_vector(irq);
+ irq_desc_t *desc = &irq_desc[vector];
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
{
desc->status &= ~IRQ_DISABLED;
if ( (desc->status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING )
- {
desc->status |= IRQ_REPLAY;
- hw_resend_irq(desc->handler,irq);
- }
desc->handler->enable(irq);
}
}
asmlinkage void do_IRQ(struct cpu_user_regs *regs)
-{
- unsigned int irq = regs->entry_vector;
- irq_desc_t *desc = &irq_desc[irq];
+{
+ unsigned int vector = regs->entry_vector;
+ unsigned int irq = vector_to_irq(vector);
+ irq_desc_t *desc = &irq_desc[vector];
struct irqaction *action;
perfc_incrc(irqs);
if ( likely(desc->status & IRQ_GUEST) )
{
- __do_IRQ_guest(irq);
+ __do_IRQ_guest(vector);
spin_unlock(&desc->lock);
return;
}
while ( desc->status & IRQ_PENDING )
{
desc->status &= ~IRQ_PENDING;
- irq_enter(smp_processor_id(), irq);
+ irq_enter(smp_processor_id());
spin_unlock_irq(&desc->lock);
action->handler(irq, action->dev_id, regs);
spin_lock_irq(&desc->lock);
- irq_exit(smp_processor_id(), irq);
+ irq_exit(smp_processor_id());
}
desc->status &= ~IRQ_INPROGRESS;
void free_irq(unsigned int irq)
{
- irq_desc_t *desc = &irq_desc[irq];
+ unsigned int vector = irq_to_vector(irq);
+ irq_desc_t *desc = &irq_desc[vector];
unsigned long flags;
spin_lock_irqsave(&desc->lock,flags);
spin_unlock_irqrestore(&desc->lock,flags);
/* Wait to make sure it's not being used on another CPU */
- do { smp_mb(); } while ( irq_desc[irq].status & IRQ_INPROGRESS );
+ do { smp_mb(); } while ( desc->status & IRQ_INPROGRESS );
}
int setup_irq(unsigned int irq, struct irqaction *new)
{
- irq_desc_t *desc = &irq_desc[irq];
+ unsigned int vector = irq_to_vector(irq);
+ irq_desc_t *desc = &irq_desc[vector];
unsigned long flags;
spin_lock_irqsave(&desc->lock,flags);
struct domain *guest[IRQ_MAX_GUESTS];
} irq_guest_action_t;
-static void __do_IRQ_guest(int irq)
+static void __do_IRQ_guest(int vector)
{
- irq_desc_t *desc = &irq_desc[irq];
+ unsigned int irq = vector_to_irq(vector);
+ irq_desc_t *desc = &irq_desc[vector];
irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
struct domain *d;
int i;
j = find_first_set_bit(m);
m &= ~(1 << j);
pirq = (i << 5) + j;
- desc = &irq_desc[pirq];
+ desc = &irq_desc[irq_to_vector(pirq)];
spin_lock_irq(&desc->lock);
if ( !test_bit(d->pirq_to_evtchn[pirq], &s->evtchn_mask[0]) &&
test_and_clear_bit(pirq, &d->pirq_mask) &&
int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
{
+ unsigned int vector = irq_to_vector(irq);
struct domain *d = v->domain;
- irq_desc_t *desc = &irq_desc[irq];
+ irq_desc_t *desc = &irq_desc[vector];
irq_guest_action_t *action;
unsigned long flags;
int rc = 0;
if ( !IS_CAPABLE_PHYSDEV(d) )
return -EPERM;
+ if ( vector == 0 )
+ return -EBUSY;
+
spin_lock_irqsave(&desc->lock, flags);
action = (irq_guest_action_t *)desc->action;
int pirq_guest_unbind(struct domain *d, int irq)
{
- irq_desc_t *desc = &irq_desc[irq];
+ unsigned int vector = irq_to_vector(irq);
+ irq_desc_t *desc = &irq_desc[vector];
irq_guest_action_t *action;
unsigned long flags;
int i;
+ BUG_ON(vector == 0);
+
spin_lock_irqsave(&desc->lock, flags);
action = (irq_guest_action_t *)desc->action;
spin_unlock_irqrestore(&desc->lock, flags);
return 0;
}
-
-int pirq_guest_bindable(int irq, int will_share)
-{
- irq_desc_t *desc = &irq_desc[irq];
- irq_guest_action_t *action;
- unsigned long flags;
- int okay;
-
- spin_lock_irqsave(&desc->lock, flags);
-
- action = (irq_guest_action_t *)desc->action;
-
- /*
- * To be bindable the IRQ must either be not currently bound (1), or
- * it must be shareable (2) and not at its share limit (3).
- */
- okay = ((!(desc->status & IRQ_GUEST) && (action == NULL)) || /* 1 */
- (action->shareable && will_share && /* 2 */
- (action->nr_guests != IRQ_MAX_GUESTS))); /* 3 */
-
- spin_unlock_irqrestore(&desc->lock, flags);
- return okay;
-}
break;
op.u.irq_status_query.flags = 0;
/* Edge-triggered interrupts don't need an explicit unmask downcall. */
- if ( strstr(irq_desc[irq].handler->typename, "edge") == NULL )
+ if ( strstr(irq_desc[irq_to_vector(irq)].handler->typename, "edge") == NULL )
op.u.irq_status_query.flags |= PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY;
ret = 0;
break;
return -EINVAL;
op.u.irq_op.vector = assign_irq_vector(irq);
- set_intr_gate(op.u.irq_op.vector, interrupt[irq]);
ret = 0;
break;
#if 0
void __init smp_intr_init(void)
{
- /*
- * IRQ0 must be given a fixed assignment and initialized,
- * because it's used before the IO-APIC is set up.
- */
- set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
-
/*
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
* IPI, driven by wakeup.
#define in_irq() (local_irq_count(smp_processor_id()) != 0)
-#define irq_enter(cpu, irq) (local_irq_count(cpu)++)
-#define irq_exit(cpu, irq) (local_irq_count(cpu)--)
+#define irq_enter(cpu) (local_irq_count(cpu)++)
+#define irq_exit(cpu) (local_irq_count(cpu)--)
#endif /* __ASM_HARDIRQ_H */
#include <asm/asm_defns.h>
#include <irq_vectors.h>
-extern void disable_irq(unsigned int);
+#define IO_APIC_IRQ(irq) (((irq) >= 16) || ((1<<(irq)) & io_apic_irqs))
+#define IO_APIC_VECTOR(irq) (irq_vector[irq])
+#define LEGACY_VECTOR(irq) ((irq) + FIRST_EXTERNAL_VECTOR)
+#define irq_to_vector(irq) \
+ (IO_APIC_IRQ(irq) ? IO_APIC_VECTOR(irq) : LEGACY_VECTOR(irq))
+#define vector_to_irq(vec) (vector_irq[vec])
+
extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int);
extern int vector_irq[NR_VECTORS];
extern u8 irq_vector[NR_IRQ_VECTORS];
-#define IO_APIC_VECTOR(irq) irq_vector[irq]
#define AUTO_ASSIGN -1
-extern void (*interrupt[NR_IRQS])(void);
-
#define platform_legacy_irq(irq) ((irq) < 16)
void disable_8259A_irq(unsigned int irq);
extern atomic_t irq_err_count;
extern atomic_t irq_mis_count;
-#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
-
-static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
-{
- if (IO_APIC_IRQ(i))
- send_IPI_self(IO_APIC_VECTOR(i));
-}
-
#endif /* _ASM_HW_IRQ_H */
extern int pirq_guest_unmask(struct domain *p);
extern int pirq_guest_bind(struct vcpu *p, int irq, int will_share);
extern int pirq_guest_unbind(struct domain *p, int irq);
-extern int pirq_guest_bindable(int irq, int will_share);
#endif /* __XEN_IRQ_H__ */